
package com.filetransfer.server.fileserver;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

import com.filetransfer.client.state.ServerReceiveControl;
import com.filetransfer.config.FileServerConfig;
import com.filetransfer.transport.command.FileInfoMessage;
import com.filetransfer.transport.util.XStreamWireFormat;
import com.filetransfer.util.FileUtil;
import com.filetransfer.util.LogUtil;
import com.filetransfer.util.ReceiveFileUtil;


/**
 * 功能说明:  <br>
 * 开发人员: hanxuetong <br>
 * 开发时间: 2014-7-25 <br>
 * ======== ====== ============================================ <br>
 * 
 */
public class ReceiveFileHandle implements Runnable{

	private ServerReceiveControl serverReceiveControl;

	private Socket sock;
	//private String path;

	ReceiveFileHandle(Socket sock, ServerReceiveControl serverReceiveControl) throws IOException {
	
		this.sock = sock;
		if(serverReceiveControl==null)
		{
			throw new RuntimeException("serverReceiveControl不能为空 ");
		}
		this.serverReceiveControl=serverReceiveControl;	
	}

	public void run() {
		
		DataInputStream sockIn=null;
		OutputStream sockOut =null;
		//FileInfo fileInfo=new FileInfo();
		
		try {
			sock.setSoTimeout(serverReceiveControl.getFileServerConfig().getSoTimeout());
			String ip = sock.getInetAddress().getHostAddress(); // 获取客户端ip
			LogUtil.echo("开启新线程接收来自客户端IP: " + ip + " 的文件");
			sockIn= new DataInputStream(new BufferedInputStream(sock.getInputStream()));
			sockOut = sock.getOutputStream();
			String messageXml=sockIn.readUTF();
			
			FileInfoMessage fileInfoMessage=XStreamWireFormat.unmarshalText(messageXml,FileInfoMessage.class);
			fileInfoMessage.setFromIp(ip);
			if(fileInfoMessage.isTransit())
			{
				/*String transferToHostParseInfo=fileInfoMessage.getToHostString();
				transferToHostParseInfo+=ToHostParseUtil.MSG_IP_REG+ip+"]";
				fileInfoMessage.setToHostString(transferToHostParseInfo);*/
				fileInfoMessage.setReplyIp(ip);
				
			}
			
			LogUtil.op("filename   :  " + serverReceiveControl.getFileServerConfig().getReceiveFileSavePath() + File.separator +fileInfoMessage.getWantRelativePath());

			if(serverReceiveControl.getServerFilePlugin()!=null)
			{
				boolean isReturn=serverReceiveControl.getServerFilePlugin().receiveFileInfoMessageBefore(fileInfoMessage);
				if(isReturn)
				{
					writeOutInfo(sockOut, fileInfoMessage.getReplyInfo());
					return;
				}
			}
			if(fileInfoMessage!=null)
			{
				writeOutInfo(sockOut, "startSend"); //开始传输
				receiveFile(fileInfoMessage,sockIn,sockOut );
			}
		
			
		} catch (Exception e) {
		
			e.printStackTrace();
		}finally{
			
			try {
				sockIn.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			
			try {
				sockOut.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			
			try {
				sock.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	
	
	private void receiveFile(FileInfoMessage fileInfoMessage,DataInputStream sockIn,OutputStream sockOut )
	{
		
		@SuppressWarnings("unused")
		long fsize=fileInfoMessage.getFileSize();
		String realpath = serverReceiveControl.getFileServerConfig().getReceiveFileSavePath() + File.separator + fileInfoMessage.getWantRelativePath().replace("/", "\\");
	//	fileInfo.setFilePath(realpath);
		fileInfoMessage.setAbsolutePath(realpath);
		
		@SuppressWarnings("unused")
		long passedlen = 0;
		File f = new File(realpath);
		FileOutputStream fos=null;
		try {
			FileUtil.CreateFile(realpath);			
//	writeOutInfo(sockOut, "FileSendNow"); // 告诉客户端,开始传送数据吧			
			fos = new FileOutputStream(f);
			byte[] bufFile = new byte[8192]; // 接收数据的缓存
			int len = 0;
			while (true) {
				
				if((len=sockIn.read(bufFile))>-1){
					fos.write(bufFile, 0, len); // 写入硬盘文件
					//fos.flush();
					 passedlen += len;				
				}
					else {
					break;
				}
			}
			// LogUtil.echo("文件接收了 "+(passedlen * 100/ fsize)+"% 为"+passedlen+" ");


			//String nowFileMd5=MD5Util.getMD5(new File(realpath));
			
			//判断md5是否正确
			if(ReceiveFileUtil.checkIsReceiveSucess(fileInfoMessage, new File(realpath),fileInfoMessage.isMd5Check()))
			{
				writeOutInfo(sockOut, "sucess"); // 文件接收成功后给客户端反馈一个信息

				serverReceiveControl.sucessReceiveFileCall(fileInfoMessage);
				
				
				LogUtil.echo(f.getAbsolutePath()+" 接收成功！");
			}else{
				
				serverReceiveControl.failReceiveFileCall(fileInfoMessage);
				writeOutInfo(sockOut, "fault"); 
				
			}
			
			//LogUtil.echo(f.getAbsolutePath()+"文件接收成功!" + System.getProperty("line.separator")); // 服务端打印一下
		} catch (Exception e) {
			
			serverReceiveControl.failReceiveFileCall(fileInfoMessage);
			
			LogUtil.err(e.getMessage(), e);
		}finally{
			if(fos!=null)
			{
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				
			}
			
		}
	
	}
		
	
	/**
	 * 将信息反馈给服务端
	 * 
	 * @param sock
	 * @param infoStr
	 * @throws Exception
	 */
	public void writeOutInfo(OutputStream sockOut, String infoStr) throws Exception {
		
		sockOut.write(infoStr.getBytes());
		sockOut.flush();
	}

}
